import type { HttpInterceptorManagerSpec, HttpRequestInterceptor, HttpResponseInterceptor } from '@/config/httpClient/HttpInterceptor.ts'
import type { AxiosInstance } from 'axios'

/**
 * 拦截器管理器
 *
 * 包装 axios 对拦截器的管理, 使用唯一名称注册和移除拦截器
 */
export class HttpInterceptorManager implements HttpInterceptorManagerSpec {

    private readonly axios: AxiosInstance

    private readonly requestInterceptor: Map<string, [ HttpRequestInterceptor, number ]> = new Map()

    private readonly responseInterceptor: Map<string, [ HttpResponseInterceptor, number ]> = new Map()


    public constructor(axios: AxiosInstance) {
        this.axios = axios
    }

    /**
     * 添加请求拦截器
     * @param interceptor 拦截器
     * @param name 可选: 拦截器名称, 唯一
     */
    addRequestInterceptor(interceptor: HttpRequestInterceptor, name: string = ''): void {
        const index = this.axios.interceptors.request.use(
                interceptor.onFulfilled.bind(interceptor) as any,
                interceptor.onRejected?.bind(interceptor),
                interceptor.options,
        )
        this.requestInterceptor.set(name, [ interceptor, index ])
    }

    /**
     * 移除请求拦截器
     * @param name 注册时名称 不能为空
     */
    removeRequestInterceptor(name: string): void {
        if (!name) {
            return
        }

        const value = this.requestInterceptor.get(name)
        if (!value) {
            return
        }
        const [ _, index ] = value
        this.axios.interceptors.request.eject(index)
    }

    /**
     * 添加响应拦截器
     * @param interceptor 拦截器
     * @param name 可选: 拦截器名称, 唯一
     */
    addResponseInterceptor(interceptor: HttpResponseInterceptor, name: string = ''): void {
        const index = this.axios.interceptors.response.use(
                interceptor.onFulfilled.bind(interceptor),
                interceptor.onRejected?.bind(interceptor),
        )
        this.responseInterceptor.set(name, [ interceptor, index ])
    }

    /**
     * 移除响应拦截器
     * @param name 注册时名称 不能为空
     */
    removeResponseInterceptor(name: string): void {
        if (!name) {
            return
        }

        const value = this.responseInterceptor.get(name)
        if (!value) {
            return
        }
        const [ _, index ] = value
        this.axios.interceptors.response.eject(index)
    }

}
